#include "stm32.h"

// 客户端线程参数结构体
typedef struct
{
    int client_socket;
    char client_ip[INET_ADDRSTRLEN];
    int client_port;
    void *node_p;
    int *total;
    struct std_node *node_arr;
    int *connection_status;        // 新增：连接状态标志
    pthread_mutex_t *status_mutex; // 新增：状态锁
} ClientThreadArgs;

// 全局变量
int server_socket;
pthread_mutex_t data_mutex = PTHREAD_MUTEX_INITIALIZER;

// 控制线程函数
void *md_control(void *arg)
{
    ClientThreadArgs *args = (ClientThreadArgs *)arg;
    int client_socket = args->client_socket;
    struct msgbuf recv_buf;
    int *connection_status = args->connection_status;
    pthread_mutex_t *status_mutex = args->status_mutex;

    while (1)
    {
        // 检查连接状态（保持不变）
        pthread_mutex_lock(status_mutex);
        if (*connection_status == 0)
        {
            pthread_mutex_unlock(status_mutex);
            break;
        }
        pthread_mutex_unlock(status_mutex);

        // 从消息队列读取指令（非阻塞模式，保持不变）
        if (msg_queue_recv("topic", &recv_buf, sizeof(recv_buf), 1, IPC_NOWAIT) > 0)
        {
            printf("Received control command: %s\n", recv_buf.mdata);
            if (recv_buf.mtype == 1)
            {
                const char *cmd = recv_buf.mdata;
                size_t cmd_len = strlen(cmd); // 计算指令实际长度
                int retry_count = 5;         // 增加重试次数至5次

                while (retry_count > 0)
                {
                    // **关键修改1：使用循环发送确保数据完整传输**
                    ssize_t sent = 0;
                    while (sent < cmd_len)
                    {
                        ssize_t ret = send(client_socket, cmd + sent, cmd_len - sent, 0);
                        if (ret < 0)
                        {
                            if (errno == EAGAIN || errno == EWOULDBLOCK)
                            {
                                usleep(10000); // 短暂休眠后重试
                                continue;
                            }
                            perror("send error:");
                            // 标记连接断开并退出
                            pthread_mutex_lock(status_mutex);
                            *connection_status = 0;
                            pthread_mutex_unlock(status_mutex);
                            close(client_socket);
                            return NULL;
                        }
                        sent += ret;
                    }

                    if (sent == cmd_len)
                    {
                        printf("指令发送成功: %s\n", cmd);
                        // 打印状态（保持不变）
                        if (strcmp(cmd, "FAN_ON") == 0) {
                            printf("-----------------搅拌设备已开启！-----------------\n");
                        } else if (strcmp(cmd, "FAN_OFF") == 0) {
                            printf("-----------------搅拌设备已关闭！-----------------\n");
                        } else if (strcmp(cmd, "BUZZ_ON") == 0) {
                            printf("-----------------警报已开启！-----------------\n");
                        } else if (strcmp(cmd, "BUZZ_OFF") == 0) {
                            printf("-----------------警报已关闭！-----------------\n");
                        }
                        break; // 发送成功，退出重试循环
                    }
                    retry_count--;
                    usleep(50000); // 重试间隔缩短至50ms
                }

                if (retry_count == 0)
                {
                    // 重试耗尽，断开连接（保持不变）
                    pthread_mutex_lock(status_mutex);
                    *connection_status = 0;
                    pthread_mutex_unlock(status_mutex);
                    close(client_socket);
                    return NULL;
                }
            }
        }
        else if (errno != ENOMSG && errno != EAGAIN)
        {
            perror("msg_queue_recv error:");
            // 标记连接断开并退出（保持不变）
            pthread_mutex_lock(status_mutex);
            *connection_status = 0;
            pthread_mutex_unlock(status_mutex);
            close(client_socket);
            return NULL;
        }

        // **关键修改2：降低休眠时间，提升状态检查频率**
        usleep(20000); // 从100ms缩短至20ms，减少状态检查延迟
    }

    return NULL;
}

// 处理 JSON 的线程函数
void *handle_json(void *arg)
{
    ClientThreadArgs *args = (ClientThreadArgs *)arg;
    char *json_data = (char *)args->node_p;
    int *total = args->total;
    struct std_node *node_arr = args->node_arr;

    // 解析 JSON 数据（不加锁，只读操作）
    cJSON *root = cJSON_Parse(json_data);
    if (root == NULL)
    {
        printf("JSON 解析失败: %s\n", cJSON_GetErrorPtr());
        free(json_data); // 提前释放内存
        return NULL;
    }

    cJSON *data = cJSON_GetObjectItem(root, "data");
    if (!data) // 新增：检查 data 节点是否存在
    {
        cJSON_Delete(root);
        free(json_data);
        return NULL;
    }

    // 加锁保护共享资源（仅在修改时加锁）
    pthread_mutex_lock(&data_mutex);
    *total = cJSON_GetArraySize(data); // 更新 total（共享变量）

    // 遍历数据项并修改 node_arr（共享数组）
    for (int i = 0; i < stm32_num && i < cJSON_GetArraySize(data); i++)
    {
        cJSON *item = cJSON_GetArrayItem(data, i);
        if (!item)
            continue; // 新增：检查数组元素是否为空

        const char *name = cJSON_GetObjectItem(item, "name")->valuestring;
        double value = cJSON_GetObjectItem(item, "value")->valuedouble;

        // 确保 stm32_arr 已初始化（避免访问未分配内存）
        if (i >= stm32_num || !stm32_arr)
        {
            pthread_mutex_unlock(&data_mutex);
            cJSON_Delete(root);
            free(json_data);
            return NULL;
        }

        node_arr[i].key = 301 + i;
        node_arr[i].type = stm32_arr[i].type;
        node_arr[i].dev_type = 1;
        node_arr[i].old_val.f_val = Past;
        Past = value;
        node_arr[i].new_val.f_val = Past;
        node_arr[i].ret = 0;

        printf("解析数据: name=%s, value=%.2lf\n", name, Past);
    }
    cJSON_Delete(root);
    pthread_mutex_unlock(&data_mutex);
    free(json_data); // 解锁后释放内存
    return NULL;
}

// 处理客户端连接的线程函数
void *handle_client(void *arg)
{
    ClientThreadArgs *args = (ClientThreadArgs *)arg;
    int client_socket = args->client_socket;
    char *client_ip = args->client_ip;
    int client_port = args->client_port;
    int *connection_status = args->connection_status;
    pthread_mutex_t *status_mutex = args->status_mutex;

    printf("[服务器] 客户端 %s:%d 已连接\n", client_ip, client_port);

    // **关键修改3：延长socket超时时间至30秒**
    struct timeval timeout;
    timeout.tv_sec = 30; // 超时时间从5秒延长至30秒
    timeout.tv_usec = 0;
    setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
    setsockopt(client_socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));

    char buf[BUFFER_SIZE];

    // 创建控制线程（保持不变）
    pthread_t md_tid;
    pthread_create(&md_tid, NULL, md_control, args);
    pthread_detach(md_tid);

    while (1)
    {
        // 检查连接状态（保持不变）
        pthread_mutex_lock(status_mutex);
        if (*connection_status == 0)
        {
            pthread_mutex_unlock(status_mutex);
            break;
        }
        pthread_mutex_unlock(status_mutex);

        memset(buf, 0, BUFFER_SIZE);
        int ret = recv(client_socket, buf, sizeof(buf), 0);

        // **关键修改4：区分recv的超时错误与真正断开**
        if (ret < 0)
        {
            if (errno == EAGAIN || errno == EWOULDBLOCK)
            {
                // 超时但连接未断开，继续循环
                continue;
            }
            perror("recv error:");
            // 标记连接断开（保持不变）
            pthread_mutex_lock(status_mutex);
            *connection_status = 0;
            pthread_mutex_unlock(status_mutex);
            close(client_socket);
            break;
        }
        else if (ret == 0)
        {
            // 客户端主动断开（保持不变）
            printf("[服务器] 客户端 %s:%d 主动断开连接\n", client_ip, client_port);
            break;
        }
        else
        {
            // 处理接收数据（保持不变）
            printf("[来自 %s:%d] %s\n", client_ip, client_port, buf);
            char *json_copy = (char *)malloc(ret + 1);
            if (!json_copy)
            {
                printf("内存分配失败，跳过当前消息\n");
                continue;
            }
            strcpy(json_copy, buf);
            args->node_p = json_copy;
            pthread_t json_tid;
            pthread_create(&json_tid, NULL, handle_json, args);
            pthread_detach(json_tid);
        }
    }

    free(args);
    return NULL;
}

void JSON_config()
{
    // 从config.json文件中读取JSON数据
    FILE *fp = fopen("config.json", "r");
    if (fp == NULL)
    {
        printf("无法打开文件\n");
        return;
    }
    // 读取文件内容到字符串
    fseek(fp, 0, SEEK_END);
    long fsize = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    char *json_str = (char *)malloc(fsize + 1);
    if (!json_str)
    {
        printf("内存分配失败\n");
        fclose(fp);
        return;
    }
    fread(json_str, 1, fsize, fp);
    fclose(fp);
    json_str[fsize] = '\0'; // 添加字符串结束符
    // 解析JSON数据
    cJSON *root = cJSON_Parse(json_str);
    if (root == NULL)
    {
        printf("解析JSON数据失败\n");
        free(json_str);
        return;
    }
    // 获取节点数组
    cJSON *stm32 = cJSON_GetObjectItem(root, "stm32");
    cJSON *data = cJSON_GetObjectItem(stm32, "data");
    // 获取modbus节点个数
    cJSON *modbus = cJSON_GetObjectItem(root, "modbus");
    cJSON *data1 = cJSON_GetObjectItem(modbus, "data");
    // 获取两个节点总和
    stm32_num = cJSON_GetArraySize(data);
    modbus_num = cJSON_GetArraySize(data1);
    total_num = modbus_num + stm32_num;
    // 打印三个节点个数
    printf("modbus_num = %d\n", modbus_num);
    printf("stm32_num = %d\n", stm32_num);
    printf("total_num = %d\n", total_num);

    // 遍历节点数组
    int arr_size = cJSON_GetArraySize(data);
    stm32_arr = (struct std_node *)malloc(arr_size * sizeof(struct std_node));

    for (int i = 0; i < arr_size; i++)
    {
        cJSON *item = cJSON_GetArrayItem(data, i);
        stm32_arr[i].key = cJSON_GetObjectItem(item, "key")->valueint;
        stm32_arr[i].type = cJSON_GetObjectItem(item, "type")->valueint;
    }

    // 解析出mqtt_server的addr和port
    cJSON *mqtt_server = cJSON_GetObjectItem(root, "mqtt_server");
    strcpy(IP, cJSON_GetObjectItem(mqtt_server, "addr")->valuestring);
    // 在IP后面添加\0
    for (int i = 0; i < strlen(IP); i++)
    {
        if (IP[i] == ',')
        {
            IP[i] = '\0';
            break;
        }
    }
    PORT = cJSON_GetObjectItem(mqtt_server, "port")->valueint;
    // 释放内存
    cJSON_Delete(root);
    free(json_str);
}

int main()
{
    JSON_config();
    // JSON_parse();

    // 初始化共享内存（仅一次）
    int shmid = shm_init(&para, "shm_test", 1024);
    if (shmid < 0)
    {
        perror("shm_init err");
        return -1;
    }

    // 获取共享内存地址
    void *node_p = shm_getaddr(&para);
    if (node_p == NULL)
    {
        perror("shm_getaddr err");
        return -1;
    }

    int *total = (int *)node_p;
    struct std_node *node_arr = (struct std_node *)(node_p + sizeof(int));

    struct sockaddr_in server_addr, client_addr;
    socklen_t addr_len = sizeof(client_addr);

    // 创建套接字
    server_socket = socket(AF_INET, SOCK_STREAM, 0);

    // 设置地址重用
    int opt = 1;
    setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    // 绑定地址和端口
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(IP);
    server_addr.sin_port = htons(PORT);

    bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr));
    listen(server_socket, 5);

    printf("[服务器] 已启动，监听地址: %s:%d\n",
           inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port));

    // 主循环：接受客户端连接并创建线程
    while (1)
    {
        int client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &addr_len);

        ClientThreadArgs *args = (ClientThreadArgs *)malloc(sizeof(ClientThreadArgs));
        if (!args)
        {
            perror("内存分配失败");
            close(client_socket);
            continue;
        }

        // 初始化连接状态
        int *connection_status = (int *)malloc(sizeof(int));
        *connection_status = 1;

        // 初始化状态锁
        pthread_mutex_t *status_mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
        pthread_mutex_init(status_mutex, NULL);

        args->client_socket = client_socket;
        inet_ntop(AF_INET, &client_addr.sin_addr, args->client_ip, INET_ADDRSTRLEN);
        args->client_port = ntohs(client_addr.sin_port);
        args->node_p = node_p;
        args->total = total;
        args->node_arr = node_arr;
        args->connection_status = connection_status;
        args->status_mutex = status_mutex;

        pthread_t tid;
        pthread_create(&tid, NULL, handle_client, args);
        pthread_detach(tid);
    }

    // 清理资源
    shmdt(node_p);
    shmctl(shmid, IPC_RMID, NULL);
    if (stm32_arr)
        free(stm32_arr);
    close(server_socket);
    return 0;
}